/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package kebut.ui;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;
import kebut.file.FileProcessor;
import kebut.file.SoundPlayer;
import kebut.logic.stegano;
import kebut.logic.vinegere;
import kebut.main.MainKebut;

public class UI extends JPanel implements MouseListener, MouseMotionListener{
    
    public static void main(String[] args) {
        MainKebut.init();
    }
    
    public JFrame frame;
    public int outF;
    
    //format
    public DecimalFormat format = new DecimalFormat("#.##");
    
    //konstanta output
    public static final int OUT_NOTHING = 0;
    public static final int OUT_WAV = 1;
    public static final int OUT_TEXT = 2;
    
    //Button Adapter
    public boolean outIsWav = true;
    public int active = -1;
    public int sound = -1;
    public ArrayList<SteButton> button;
    
    //Image
    public BufferedImage[][] img;
    public int[] state;
    
    //Font
    public static final Font F_TEXT = new Font("Trebuchet MS", Font.BOLD, 19);
    
    //Warna
    public static final Color CL_BG = Color.decode("#3f394b");
    public static final Color CL_BOX = Color.decode("#5a6e79");
    public static final Color CL_DETAIL = Color.decode("#b0b05c");
    
    //Konstanta gambar
    public static final int IMG_TITLE = 0;
    public static final int IMG_TXINTX = 1;
    public static final int IMG_TXBOX = 2;
    public static final int IMG_BTOPEN = 3;
    public static final int IMG_BTBROWSE = 4;
    public static final int IMG_TXINWAV = 5;
    public static final int IMG_BTPLAY = 6;
    public static final int IMG_BTPAUSE = 7;
    public static final int IMG_BTSTOP = 8;
    public static final int IMG_TXKEY = 9;
    public static final int IMG_TXLSB = 10;
    public static final int IMG_BTEN = 11;
    public static final int IMG_BTDE = 12;
    public static final int IMG_TXOUT = 13;
    public static final int IMG_DETAILS = 14;
    public static final int IMG_BTSAVE = 15;
    public static final int IMG_SENTINEL = 16;
    
    //Konstanta status gambar
    public static final int S_NORMAL = 0;
    public static final int S_HOVER = 1;
    public static final int S_PRESS = 2;
    
    //cursor
    public static final Cursor HAND_CURSOR = new Cursor(Cursor.HAND_CURSOR);
    public static final Cursor NORMAL_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR);
    
    //Textbox
    public JTextField plainTx,          //input text
                        wavTx,          //input wav
                        keyTx,          //key code
                        lsbTx,          //bit lsb
                        outTx;          //output 
    
    //Scrollbar Details
    public JScrollPane detailsPane;
    public JTextArea detailsArea;
   
    public UI() {
         super();
         initImg();
         initComponent();
         initButton();
         repaint();
    }
    
    private void initComponent() {
        setLayout(null);
        setSize(810,610);
        
        frame = new JFrame("Lelegano v1.0");
        frame.setSize(810, 620);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(this);
        frame.setVisible(true);
        
        //Textfield
        plainTx = new JTextField("");
        wavTx = new JTextField("");
        keyTx = new JTextField("");
        lsbTx = new JTextField("");
        outTx = new JTextField("");
        
        plainTx.setEditable(false);
        wavTx.setEditable(false);
        outTx.setEditable(false);
        
        plainTx.setFont(F_TEXT);
        wavTx.setFont(F_TEXT);
        outTx.setFont(F_TEXT);
        keyTx.setFont(F_TEXT);
        lsbTx.setFont(F_TEXT);
        
        plainTx.setBorder(null);
        wavTx.setBorder(null);
        outTx.setBorder(null);
        keyTx.setBorder(null);
        lsbTx.setBorder(null);
        
        plainTx.setBackground(CL_BG);
        wavTx.setBackground(CL_BG);
        outTx.setBackground(CL_BG);
        keyTx.setBackground(CL_BG);
        lsbTx.setBackground(CL_BG);
        
        plainTx.setForeground(CL_DETAIL);
        wavTx.setForeground(CL_DETAIL);
        outTx.setForeground(CL_DETAIL);
        keyTx.setForeground(CL_DETAIL);
        lsbTx.setForeground(CL_DETAIL);
        
        plainTx.setBounds(45,111,480,25);
        wavTx.setBounds(45,183,480,25);
        outTx.setBounds(45,335,480,25);
        keyTx.setBounds(76,245,188,25);
        lsbTx.setBounds(352,245,46,25);
        
        add(plainTx);
        add(wavTx);
        add(outTx);
        add(keyTx);
        add(lsbTx);
        
        //scrollbar details
        detailsArea = new JTextArea(5,30);
        detailsArea.setFont(F_TEXT);
        detailsArea.setLineWrap(true);
        detailsArea.setWrapStyleWord(true);
        detailsArea.setBackground(CL_DETAIL);
        detailsArea.setForeground(CL_BG);
        detailsPane = new JScrollPane(detailsArea);
        detailsPane.setBounds(10,440,790,150);
        detailsPane.setBorder(null);
        
        add(detailsPane);
        
        addMouseMotionListener(this);
        addMouseListener(this);
    }
    
    private void initImg() {
        img = new BufferedImage[IMG_SENTINEL][1];
        state = new int[IMG_SENTINEL];
        for (int i = 0; i < IMG_SENTINEL; i++) {
            state[i] = S_NORMAL;
        }
        try {
            img[IMG_TITLE][0] = ImageIO.read(new File("images/lelegano_03.png"));
            img[IMG_TXINTX][0] = ImageIO.read(new File("images/lelegano_06.png"));
            img[IMG_TXBOX][0] = ImageIO.read(new File("images/lelegano_08.png"));
            img[IMG_BTOPEN][0] = ImageIO.read(new File("images/lelegano_10.png"));
            img[IMG_BTBROWSE][0] = ImageIO.read(new File("images/lelegano_12.png"));
            img[IMG_TXINWAV][0] = ImageIO.read(new File("images/lelegano_14.png"));
            img[IMG_BTPLAY][0] = ImageIO.read(new File("images/lelegano_17.png"));
            img[IMG_BTPAUSE][0] = ImageIO.read(new File("images/lelegano_18.png"));
            img[IMG_BTSTOP][0] = ImageIO.read(new File("images/lelegano_19.png"));
            img[IMG_TXKEY][0] = ImageIO.read(new File("images/lelegano_22.png"));
            img[IMG_TXLSB][0] = ImageIO.read(new File("images/lelegano_24.png"));
            img[IMG_BTEN][0] = ImageIO.read(new File("images/lelegano_26.png"));
            img[IMG_BTDE][0] = ImageIO.read(new File("images/lelegano_28.png"));
            img[IMG_TXOUT][0] = ImageIO.read(new File("images/lelegano_35.png"));
            img[IMG_DETAILS][0] = ImageIO.read(new File("images/lelegano_44.png"));
            img[IMG_BTSAVE][0] = ImageIO.read(new File("images/lelegano_45.png"));
        } catch (IOException ioe) {
            System.out.println("ERROR ON LOADING IMAGE!");
        }
    }
    
    private void initButton() {
        button = new ArrayList<SteButton>();
        button.add(new SteButton("open_intx",IMG_BTOPEN,560,105,110,40));             //0
        button.add(new SteButton("browse_intx",IMG_BTBROWSE,680,105,112,40));          //1
        button.add(new SteButton("play_inwav",IMG_BTPLAY,560,177,35,40));               //2
        button.add(new SteButton("pause_inwav",IMG_BTPAUSE,598,177,35,40));             //3
        button.add(new SteButton("stop_inwav",IMG_BTSTOP,637,177,35,40));               //4
        button.add(new SteButton("browse_inwav",IMG_BTBROWSE,680,177,112,40));          //5
        button.add(new SteButton("enkrip",IMG_BTEN,430,238,120,40));                    //6
        button.add(new SteButton("dekrip",IMG_BTDE,566,238,120,40));                    //7
        button.add(new SteButton("play_out",IMG_BTPLAY,560,331,35,40,false));           //8 
        button.add(new SteButton("pause_out",IMG_BTPAUSE,598,331,35,40,false));         //9
        button.add(new SteButton("stop_out",IMG_BTSTOP,637,331,35,40,false));           //10
        button.add(new SteButton("open_out",IMG_BTOPEN,560,331,112,40,false));          //11  
        button.add(new SteButton("browse_out",IMG_BTSAVE,680,331,112,40,false));      //12
    }
    
    public void setButtonOut() {
        for (int i = 8; i < 11; i++) {
            button.get(i).visible = outIsWav;
        }
        button.get(11).visible = !outIsWav;
        button.get(12).visible = (!outTx.getText().isEmpty());
        repaint();
    }
    
    private void draw(int image, int x, int y, Graphics2D g2d) {
        g2d.drawImage(img[image][state[image]], x, y,null);
    }
    
    private void draw(SteButton button, Graphics2D g2d) {
        if (button.visible) {
            g2d.drawImage(img[button.type][button.state], button.area.x, button.area.y, null);
//            g2d.setColor(Color.RED);
//            g2d.drawRect(button.area.x, button.area.y, button.area.width, button.area.height);
        }
    }
    
    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        //BG
        g2d.setColor(CL_BG);
        g2d.fillRect(0,0,810,610);
        
        //Box
        g2d.setColor(CL_BOX);
        g2d.fillRect(0, 0, 810, 50);       //header
        g2d.fillRect(20, 123, 790, 5);     //garis input text
        g2d.fillRect(20, 195, 790, 5);     //garis input wav
        g2d.fillRect(0, 255, 685, 10);         //garis kontrol
        g2d.fillRect(20, 348, 790, 5);     //garis output
        
        //Detail
        g2d.setColor(CL_DETAIL);
        g2d.fillRect(0,430,810,180);
        
        //title
        draw(IMG_TITLE,0,10,g2d);
        draw(IMG_TXINTX,0,75,g2d);
        draw(IMG_TXBOX,15,105,g2d);
        //draw(IMG_BTOPEN,560,105,g2d);
        //draw(IMG_BTBROWSE,680,105,g2d);
        draw(IMG_TXINWAV,15,145,g2d);
        draw(IMG_TXBOX,15,177,g2d);
        //draw(IMG_BTPLAY,560,177,g2d);
        //draw(IMG_BTPAUSE,598,177,g2d);
       // draw(IMG_BTSTOP,637,177,g2d);
        //draw(IMG_BTBROWSE,680,177,g2d);
        draw(IMG_TXKEY,10,238,g2d);
        draw(IMG_TXLSB,297,238,g2d);
       // draw(IMG_BTEN,430,238,g2d);
        //draw(IMG_BTDE,566,238,g2d);
        draw(IMG_TXOUT,16,297,g2d);
        draw(IMG_TXBOX,15,330,g2d);
        //draw(IMG_BTPLAY,560,331,g2d);
        //draw(IMG_BTPAUSE,598,331,g2d);
        //draw(IMG_BTSTOP,637,331,g2d);
        //draw(IMG_BTBROWSE,680,331,g2d);
        
        //details
        draw(IMG_DETAILS,625,391,g2d);
        
        //button
        if (button != null) {
            for (SteButton bu : button){   
                draw(bu, g2d);   
            }
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        active = SteButton.find(e.getX(), e.getY(), button);
        if (active > -1) {
            button.get(active).Hover();
            setCursor(HAND_CURSOR);
        } else {
            setCursor(NORMAL_CURSOR);
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (active > -1) {
            button.get(active).Press();
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (active > -1) {
            String command = button.get(active).command;
            System.out.println(command);
            if (command.equalsIgnoreCase("open_intx")) {
                if (FileProcessor.intxt != null) {
                    try {
                        Desktop.getDesktop().open(FileProcessor.intxt);
                    } catch (IOException ioe) {
                        JOptionPane.showMessageDialog(frame, "Error opening file");
                    }
                }
            } else if (command.equalsIgnoreCase("browse_intx")) {
                try {
                    FileProcessor.loadTx();
                } catch (IOException ioe) {
                    JOptionPane.showMessageDialog(this, "Something is wrong when loading file..");
                }
            } else if (command.equalsIgnoreCase("play_inwav")) {
                if (FileProcessor.inwav != null) {
                    if (sound != 0) {
                        SoundPlayer.setMusic(FileProcessor.inwav);
                    }
                    SoundPlayer.play();
                    sound = 0;
                }
            } else if (command.equalsIgnoreCase("pause_inwav")) {
                if (sound == 0) {
                    SoundPlayer.pause();
                }
            } else if (command.equalsIgnoreCase("stop_inwav")) {
                if (sound == 0) {
                    SoundPlayer.stop();
                }
            } else if (command.equalsIgnoreCase("browse_inwav")) {
                try {
                    FileProcessor.loadWav();
                } catch (IOException ioe) {
                    JOptionPane.showMessageDialog(this, "Something is wrong when loading file..");
                }
            } else if (command.equalsIgnoreCase("enkrip")) {
                if (keyTx.getText().length() > 25) {
                    JOptionPane.showMessageDialog(frame, "Maximum length of key is 25");
                    return;
                }
                if ((Integer.parseInt(lsbTx.getText()) > 3) || (Integer.parseInt(lsbTx.getText()) < 1)) {
                    JOptionPane.showMessageDialog(frame, "Please choose LSB between 1, 2, or 3");
                    return;
                }
                int vconfirm = JOptionPane.showConfirmDialog(frame, "Do you want encrypt your file?", "Vigenere", JOptionPane.YES_NO_CANCEL_OPTION);
                byte[] temp = FileProcessor.plain;
                if (vconfirm == JOptionPane.YES_OPTION) {
                    MainKebut.vinegere = new vinegere(FileProcessor.plain, true, keyTx.getText());
                    MainKebut.vinegere.encrypt();
                    FileProcessor.plain = MainKebut.vinegere.getCipher();
                } 
                if (vconfirm != JOptionPane.CANCEL_OPTION) {
                    MainKebut.stegano = new stegano(FileProcessor.plain, FileProcessor.wav, FileProcessor.ext, keyTx.getText(), Integer.parseInt(lsbTx.getText()));
                    MainKebut.stegano.encrypt();

                    if (!MainKebut.stegano.isError) {
                        outTx.setText(FileProcessor.inwav.getName() + "_encrypted");
                        FileProcessor.wav_hasil = MainKebut.stegano.embedByte;
                        setButtonOut();
                        outIsWav = true;
                        StringBuilder log = new StringBuilder();
                        log.append("Congratulation! You have successfully embed your message.\n");
                        log.append("Here is the information : \n\n");
                        log.append("PSNR = ").append(format.format(MainKebut.stegano.countPSNR())).append(" dB\n").append((MainKebut.stegano.countPSNR() < 30)? "Your file may be damaged." : "Please save your file first.");
                        detailsArea.setText(log.toString());
                    } else {
                        JOptionPane.showMessageDialog(frame, "File size exceed payload.");
                    }
                }
                FileProcessor.plain = temp;
            } else if (command.equalsIgnoreCase("dekrip")) {
                if (keyTx.getText().length() > 25) {
                    JOptionPane.showMessageDialog(frame, "Maximum length of key is 25");
                    return;
                }
                if ((Integer.parseInt(lsbTx.getText()) > 3) || (Integer.parseInt(lsbTx.getText()) < 1)) {
                    JOptionPane.showMessageDialog(frame, "Please choose LSB between 1, 2, or 3");
                    return;
                }
                int vconfirm = JOptionPane.showConfirmDialog(frame, "Is this an encrypted file?", "Vigenere", JOptionPane.YES_NO_CANCEL_OPTION);
                if (vconfirm != JOptionPane.CANCEL_OPTION) {
                    MainKebut.stegano = new stegano(FileProcessor.wav, keyTx.getText(), Integer.parseInt(lsbTx.getText()));
                    MainKebut.stegano.decrypt();
                    FileProcessor.ext = MainKebut.stegano.extension;
                    outIsWav = false;
                    outTx.setText(FileProcessor.inwav.getName() + "_decrypted");
                    setButtonOut();
                    
                    StringBuilder log = new StringBuilder();
                    if (MainKebut.stegano.extension == null) {
                        log.append("I think you have the wrong key / LSB");
                    } else {
                        log.append("Congratulation, you have succesfully extracted your message.\n");
                        log.append("Please save your extracted message first.");
                    }
                    detailsArea.setText(log.toString());
                }
                byte[] temp = MainKebut.stegano.extractByte;
                if (vconfirm == JOptionPane.YES_OPTION) {
                    MainKebut.vinegere = new vinegere(MainKebut.stegano.extractByte, false, keyTx.getText());
                    MainKebut.vinegere.decrypt();
                    MainKebut.stegano.extractByte = MainKebut.vinegere.getPlain();
                }
                FileProcessor.plain_hasil = MainKebut.stegano.extractByte;
                MainKebut.stegano.extractByte = temp;
            } else if (command.equalsIgnoreCase("play_out")) {
                if (FileProcessor.out != null) {
                    if (sound != 1) {
                        SoundPlayer.setMusic(FileProcessor.out);
                    }
                    SoundPlayer.play();
                    sound = 1;
                }
            } else if (command.equalsIgnoreCase("pause_out")) {
                if (sound == 1) {
                    SoundPlayer.pause();
                }
            } else if (command.equalsIgnoreCase("stop_out")) {
                if (sound == 1) {
                    SoundPlayer.stop();
                }
            } else if (command.equalsIgnoreCase("browse_out")) {
                try {
                    if (outIsWav)
                        FileProcessor.saveOutWav();
                    else
                        FileProcessor.saveOutTxt();
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(this, "Something is wrong when saving file..");
                }
            } else if (command.equalsIgnoreCase("open_out")) {
                if (FileProcessor.out != null) {
                    try {
                        Desktop.getDesktop().open(FileProcessor.out);
                    } catch (IOException ioe) {
                        JOptionPane.showMessageDialog(frame, "Error opening file");
                    }
                }
            } 
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        
    }

    @Override
    public void mouseExited(MouseEvent e) {
        
    }


}